#!/usr/bin/env python
# -*- coding: ISO-8859-1 -*-
#
#      Kovan's OGBot
#      Copyright (c) 2007 by kovan 
#
#      *************************************************************************
#      *                                                                       *
#      * This program is free software; you can redistribute it and/or modify  *
#      * it under the terms of the GNU General Public License as published by  *
#      * the Free Software Foundation; either version 2 of the License, or     *
#      * (at your option) any later version.                                   *
#      *                                                                       *
#      *************************************************************************
#

import sys
import locale
import os
import os.path
import shelve
import cPickle
import re
import urllib2
import cookielib
from ctypes import *
from datetime import datetime,timedelta
from Queue import *
import threading

import PyQt4
from PyQt4 import QtCore, QtGui
from PyQt4 import uic
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
from PyQt4.QtNetwork import *
import sip
sys.path.append('src/ui')

from OGBot import *
from CommonClasses import *
from GameEntities import *
from Constants import *


class MyColors:
    lightGreen,lightRed,lightYellow,lightGrey,veryLightGrey = (QColor(191,255,191),QColor(255,191,191),QColor(255,255,191),QColor(191,191,191),QColor(223,223,223))


formclass, baseclass = uic.loadUiType("src/ui/About.ui")
class AboutDialog(baseclass,formclass): 
    def __init__(self):
        baseclass.__init__(self)        
        self.setupUi(self)


formclass, baseclass = uic.loadUiType("src/ui/WebWindow.ui")
class WebBrowser(baseclass,formclass): 
    def __init__(self, cookie, config):
        baseclass.__init__(self)        
        self.setupUi(self)
        
        self.REGEXPS = \
        {
            'cookie':re.compile(r'(?P<cookie_name>\S*?)\s*=\s*(?P<cookie_value>\S*?);', re.I | re.DOTALL)
        }
        newCookie = ''
        if cookie:
            for i in xrange(len(cookie)):
                newCookie = newCookie + cookie[len(cookie)-1-i]
                newCookie = newCookie+";"                    
        try:
            file = open(FILE_PATHS['webstate'],'r')
            server = cPickle.load(file)        
            session = cPickle.load(file)
            file.close()
        except IOError:
            self.launchBrowserButton.setEnabled(False)

        if server and session:
            self.current = "http://"+str(server)+"/game/index.php?session="+str(session)+"&page=overview"
            #self.current = "http://www.google.com"
            self.config = BotConfiguration(FILE_PATHS['config'])
            #build cookie
            cookiebase = QNetworkCookie("","")
            self.cookies = cookiebase.parseCookies("")
            
            for cookiename,cookievalue in self.REGEXPS['cookie'].findall(newCookie):
                cookie_tmp = QNetworkCookie(QByteArray(cookiename),QByteArray(cookievalue))
                self.cookies.append(cookie_tmp)            

            self.cookiejar = QNetworkCookieJar()
            self.cookiejar.setCookiesFromUrl(self.cookies, QUrl(self.current))
            self.network_manager = QNetworkAccessManager()
            self.network_manager.setCookieJar(self.cookiejar)
            proxy_tmp = QString(QByteArray(config['proxy']))

            #print proxy_tmp

            if not proxy_tmp.isEmpty():
                self.proxy = QNetworkProxy()
                self.proxy.setType(self.proxy.HttpProxy);
                proxy_tmp_new = QString("")
                #try to handle if username/password contain @
                list_tmp = proxy_tmp.split("@")
                count = list_tmp.count()
                if count > 1:
                    #contain @
                    index = 0
                    while index < count:
                        if index < count - 2:
                            proxy_tmp_new.append(list_tmp[index]).append("@")
                        elif index == count - 2:
                            proxy_tmp_new.append(list_tmp[index]).append(":")
                        else:
                            proxy_tmp_new.append(list_tmp[index])
                        index = index + 1
                else:
                    proxy_tmp_new = proxy_tmp

                #print proxy_tmp_new
                list_tmp = proxy_tmp_new.split(":")
                if list_tmp.count() != 4:
                    proxy_server = list_tmp[0]
                    proxy_port,result = list_tmp[1].toULong()
                    proxy_user = QString("")
                    proxy_password = QString("")
                else:
                    proxy_user = list_tmp[0]
                    proxy_password = list_tmp[1]
                    proxy_server = list_tmp[2]
                    proxy_port,result = list_tmp[3].toULong()

                #print proxy_user
                #print proxy_password
                #print proxy_server
                #print proxy_port

                self.proxy.setHostName(proxy_server);
                self.proxy.setPort(proxy_port);
                self.proxy.setUser(proxy_user);
                self.proxy.setPassword(proxy_password);
                self.network_manager.setProxy(self.proxy)

            self.webPage = IEWinPage()
            self.webPage.setUserAgent(self.config['userAgent'])
            self.webPage.setNetworkAccessManager(self.network_manager)

            self.frame = self.webPage.mainFrame()
            self.webView.setPage(self.webPage)
            self.setWindowTitle(str(server))
            self.frame.load(QUrl(self.current))

        

class IEWinPage(QWebPage):
    def __init__(self):
        QWebPage.__init__(self)
        self.useragent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"
    
    def setUserAgent(self, agent):
        self.useragent = agent

    def userAgentForUrl(self, url):
        return QString(QByteArray(self.useragent))
     

formclass, baseclass = uic.loadUiType("src/ui/Options.ui")
class OptionsDialog(baseclass,formclass): 
    
    def __init__(self, mainWindows):
        baseclass.__init__(self)        
        self.setupUi(self)
        self.mainWindows = mainWindows
        
        self.attackingShipButtonGroup = QButtonGroup()
        self.attackingShipButtonGroup.addButton(self.smallCargoRadioButton)
        self.attackingShipButtonGroup.addButton(self.largeCargoRadioButton)        
        
        self.lineEdits = ['webpage','language','username','password','proxy','rentabilityFormula','userAgent','deuteriumSourcePlanet','reportValidTime']
        self.spinBoxes = ['gameSpeed','attackRadius','probesToSend','probesToCheck','slotsToReserve','systemsPerGalaxy','maxProbes', 'randomShipsNumber']
        self.checkBoxes = ['enableRushMode','roundShipsNumber', 'manualDefendedAttack', 'automaticDefendedAttack']
        self.textEdits = ['playersToAvoid','alliancesToAvoid']
        self.formulas = {
                    'defaultFormula': BotConfiguration('').rentabilityFormula,
                    'bestRelation'  : '(metal + crystal + deuterium) / flightTime',
                    'mostTotal'     : 'metal + crystal + deuterium',
                    'mostMetal'     : 'metal',
                    'mostCrystal'   : 'crystal',
                    'mostDeuterium' : 'deuterium'
                    }        
                
        for name in self.formulas.keys():
            control = getattr(self,name + "RadioButton")
            QObject.connect(control,SIGNAL("clicked()"),self.updateRentabilityFormula)
        QObject.connect(self.okButton,SIGNAL("clicked()"),self.saveOptions)
        QObject.connect(self.mainPlanetRadio,SIGNAL("clicked()"),self.disablePlanetList)
        QObject.connect(self.rotatePlanetsRadio,SIGNAL("clicked()"),self.enablePlanetList)
        QObject.connect(self.addPlanetButton,SIGNAL("clicked()"),self.addPlanetToList)        
        QObject.connect(self.removePlanetButton,SIGNAL("clicked()"),self.removePlanetFromList)                
        QObject.connect(self.resetUserAgentButton,SIGNAL("clicked()"),self.resetUserAgent) 

        
        self.enableOrDisablePlanetList(False)
        self.loadOptions()
        
    def loadOptions(self):
        
        self.config = BotConfiguration(FILE_PATHS['config'])
        if os.path.isfile(FILE_PATHS['config']):
            try: self.config.load()
            except BotError, e: 
                QMessageBox.critical(self,"Error in configuration",str(e))


        radioButton = getattr(self, self.config.attackingShip + "RadioButton")
        radioButton.setChecked(True)
        
        for i in self.lineEdits:
            control = getattr(self,i + "LineEdit")
            control.setText(str(self.config[i]))
        for i in self.spinBoxes:            
            control = getattr(self,i + "SpinBox")
            control.setValue(int(self.config[i]))
        for i in self.checkBoxes:
            control = getattr(self,i + "CheckBox")
            if self.config[i] :
                control.setCheckState(Qt.Checked)
            else :
                control.setCheckState(Qt.Unchecked)
        for i in self.textEdits:            
            control = getattr(self,i + "TextEdit")
            control.setPlainText('\n'.join(self.config[i]))

        control = getattr(self,'minFreeSlotToWaitSpinBox')
        control.setValue(int(self.config['freeSlotToWait'][0]))

        control = getattr(self,'maxFreeSlotToWaitSpinBox')
        control.setValue(int(self.config['freeSlotToWait'][1]))

        if self.config.get('sourcePlanets'):
            self.rotatePlanetsRadio.setChecked(True)
            self.enablePlanetList()
            self.sourcePlanetsList.addItems( [repr(p) for p in self.config['sourcePlanets']] )

        deuteriumSourcePlanet = self.config['deuteriumSourcePlanet']
        if deuteriumSourcePlanet and deuteriumSourcePlanet.isMoon():
            self.isMoonCheckBox2.setChecked(True)
        

        formulasReversed = dict([(formula,name) for name,formula in self.formulas.items() ])
        if self.config.rentabilityFormula in formulasReversed:
            control = formulasReversed[self.config.rentabilityFormula] + "RadioButton"
            getattr(self,control).setChecked(True)
        else:
            self.customFormulaRadioButton.setChecked(True)
            
        
    def saveOptions(self):
        try: 
            for i in self.lineEdits:
                control = getattr(self,i + "LineEdit")
                self.config[i] = str(control.text())
            for i in self.spinBoxes:            
                control = getattr(self,i + "SpinBox")
                self.config[i] = str(control.value())

            for i in self.checkBoxes:
                control = getattr(self,i + "CheckBox")
                if control.checkState() == Qt.Checked :
                    self.config[i] = True
                else :
                    self.config[i] = False

            for i in self.textEdits:
                control = getattr(self,i + "TextEdit")
                self.config[i] = str(control.toPlainText()).split('\n')

            control = getattr(self,'minFreeSlotToWaitSpinBox')
            self.config['freeSlotToWait'][0] = str(control.value())

            control = getattr(self,'maxFreeSlotToWaitSpinBox')
            self.config['freeSlotToWait'][1] = str(control.value())

            if self.rotatePlanetsRadio.isChecked():
                sourcePlanets = [ Coords(str(self.sourcePlanetsList.item(i).text())) for i in range(self.sourcePlanetsList.count()) ]
                if not sourcePlanets:
                    QMessageBox.critical(self,"Error","No source of attacks planets selected")
                    return
            else: sourcePlanets = []
    
            self.config['sourcePlanets'] = sourcePlanets
            self.config['attackingShip'] = str(self.attackingShipButtonGroup.checkedButton().text())
        
            coordsStr = str(self.deuteriumSourcePlanetLineEdit.text())
            if '[::]' in coordsStr:
                deuteriumSourcePlanet = ''
            else:
                if self.isMoonCheckBox2.isChecked():
                    coordsType = Coords.Types.moon
                else:coordsType = Coords.Types.planet
                deuteriumSourcePlanet= Coords(coordsStr,coordsType = coordsType)
            self.config['deuteriumSourcePlanet'] = deuteriumSourcePlanet
            
            self.config.save()
            self.config.load()
            if self.mainWindows.bot:
                # make the bot reload the config
                self.mainWindows.bot.msgQueue.put(GuiToBotMsg(GuiToBotMsg.config))
        except Exception,e:
            QMessageBox.critical(self,"Error in configuration",str(e))
        else:
            self.accept()

    def enablePlanetList(self):
        self.enableOrDisablePlanetList(True)
        
    def disablePlanetList(self):
        self.enableOrDisablePlanetList(False)
        
    def enableOrDisablePlanetList(self,enable):
        self.addPlanetLineEdit.setEnabled(enable)
        self.addPlanetButton.setEnabled(enable)
        self.removePlanetButton.setEnabled(enable)
        self.sourcePlanetsList.setEnabled(enable)            
        self.isMoonCheckBox.setEnabled(enable)  
    
    def addPlanetToList(self):
        if self.isMoonCheckBox.isChecked():
            coordsType = Coords.Types.moon
        else : coordsType = Coords.Types.planet
        coords = Coords(str(self.addPlanetLineEdit.text()),coordsType = coordsType)
        self.sourcePlanetsList.addItem(repr(coords))
        
    def removePlanetFromList(self):
        selectedPlanet = self.sourcePlanetsList.currentItem()
        if not selectedPlanet:
            return
        index = self.sourcePlanetsList.row(selectedPlanet)
        self.sourcePlanetsList.takeItem(index)
        
    def resetUserAgent(self):
        tmpConfig = Configuration('')
        self.userAgentLineEdit.setText(tmpConfig.userAgent)

    def updateRentabilityFormula(self):
        for name,formula in self.formulas.items():
            control = getattr(self,name + "RadioButton")
            if control.isChecked():
                self.rentabilityFormulaLineEdit.setText(formula)


formclass, baseclass = uic.loadUiType("src/ui/MainWindow.ui")
class MainWindow(baseclass,formclass): 
    
    def __init__(self):
        baseclass.__init__(self)
        self.setupUi(self) # parent ui setup
        self.msgQueue = Queue()
        self._planetDb = {}
        self.bot = None
        self.botThread = None
        self.translations = None
        self.cookie = None
        self.app = None
        self.browser = None
        
        QObject.connect(qApp,SIGNAL("lastWindowClosed ()"),self.stopClicked)
        QObject.connect(self.aboutButton,SIGNAL("clicked()"),self.showAbout)
        QObject.connect(self.optionsButton,SIGNAL("clicked()"),self.showOptions)
        QObject.connect(self.scanGalaxiesButton,SIGNAL("clicked()"),self.scanGalaxies)
        QObject.connect(self.launchBrowserButton,SIGNAL("clicked()"),self.launchBrowser) 
        QObject.connect(self.startButton,SIGNAL("clicked()"),self.startClicked)
        QObject.connect(self.stopButton,SIGNAL("clicked()"),self.stopClicked)                

        self.setStatusBar(None)
        
            
        self.botActivityTree.header().setResizeMode(QHeaderView.Interactive)
        self.botActivityTree.header().setStretchLastSection(False)
        headerSizes = [70,70,90,80,55,280,60,111,162,135]
        for i in xrange(len(headerSizes)):
            self.botActivityTree.header().resizeSection(i,headerSizes[i])
        
        # Using a python threading.Timer here would NOT be safe to use here because it'd launch
        # a third thread that would access GUI data, resulting in potential data corruption. 
        # A QTimer, on the other hand, thread-safely sends a signal to the GUI thread, so 
        # the scheduled method would run in the GUI thread, and that is safe.
        
        self.timer = QTimer()
        QObject.connect(self.timer,SIGNAL("timeout()"),self._dispatchBotMessages)
        self.timer.start(500)        


        self.config = Configuration(FILE_PATHS['config'])
        try: self.config.load()
        except (BotFatalError, BotError): 
            self.showOptions()
            self.config.load() #First time will fail as a new account,so load again
        
        #print 'config.universe=',config.universe
        #print 'config.webpage=',config.webpage
        
        
        self.setWindowTitle("%s %s" %(self.windowTitle(),self.config.webpage))
        
        #For test
        #self.launchBrowserButton.setEnabled(True)
        
    def setCookie(self, cookie):
        self.cookie = cookie
        
    def getCookie(self):
        return self.cookie
    
    def _dispatchBotMessages(self):
        ''' An inter-thread message is an array whose first element is the event handler method and the rest
            are its arguments.
            This method checks the queue for new messages and converts them to method calls.
        '''
        while True:
            try:
                msg = self.msgQueue.get(False)
                if msg.methodName not in dir(self):
                    raise BotFatalError("Inter-thread message not found (%s)." % msg.methodName)
                
                method = getattr(self,msg.methodName)
                method(*msg.args)
            except Empty:
                return
 
    def startClicked(self):
        if self.startButton.text() == "Start":
            self.bot = Bot(self)
            self.botThread = threading.Thread(None,self.bot.run,"BotThread")
            self.botThread.setDaemon(True)
            self.botThread.start()            
            self.setBotStatusRunning()
            self.startButton.setText("Pause")
            self.startButton.setEnabled(False)
            print "Start press to start"
            self.stopButton.setEnabled(True)
        elif self.startButton.text() == "Pause":
            self.bot.msgQueue.put(GuiToBotMsg(GuiToBotMsg.pause))
            self.botStatusLabel.setPalette(QPalette(MyColors.lightYellow))
            self.oldStatus = self.botStatusLabel.text()
            self.botStatusLabel.setText("Paused")
            self.startButton.setText("Resume") 
            self.launchBrowserButton.setEnabled(True)
        elif self.startButton.text() == "Resume":
            self.bot.msgQueue.put(GuiToBotMsg(GuiToBotMsg.resume))
            self.launchBrowserButton.setEnabled(False)
            #print 'self.oldStatus', self.oldStatus
            if self.oldStatus == "Fleet limit hit":
                self.botStatusLabel.setPalette(QPalette(MyColors.lightYellow))
                self.botStatusLabel.setText("Fleet limit hit")
            elif self.oldStatus == "Scanning Galaxies...":
                self.botStatusLabel.setPalette(QPalette(MyColors.lightGreen))
                self.botStatusLabel.setText("Scanning Galaxies...")
            else:
                self.setBotStatusRunning()
            self.startButton.setText("Pause") 
    
    def stopClicked(self):
        if self.bot:
            self.bot.msgQueue.put(GuiToBotMsg(GuiToBotMsg.stop))
        else: return
        self.stopButton.setEnabled(False)
        self.startButton.setEnabled(True)
        print "Stop Press"
        self.scanGalaxiesButton.setEnabled(False)
        self.launchBrowserButton.setEnabled(False)        
        self.startButton.setText("Start")
        self.botStatusLabel.setPalette(QPalette(MyColors.lightRed))
        self.botStatusLabel.setText("Stopped")        
        self.connectionStatusLabel.setText("")    
        self.connectionStatusLabel.setPalette(self.palette())

    def launchBrowser(self):
        cookie = self.cookie
        config = self.config
        
        #test
        self.browser = WebBrowser(cookie,config)
        self.browser.show()
        
    def showAbout(self):
        window = AboutDialog()
        window.exec_()
        
    def showOptions(self):
        window = OptionsDialog(self)
        window.exec_()
            
    def setConnectionOK(self):
        self.connectionStatusLabel.setPalette(QPalette(MyColors.lightGreen))
        self.connectionStatusLabel.setText("OK")        
        
    def setBotStatusRunning(self):
        self.botStatusLabel.setPalette(QPalette(MyColors.lightGreen))
        self.botStatusLabel.setText("Running...")        
    
    def scanGalaxies(self):
        if self.bot:
            self.scanGalaxiesButton.setEnabled(False)
            self.startClicked() # pause the bot
            self.bot.msgQueue.put(GuiToBotMsg(GuiToBotMsg.scan)) # scan galaxies
            self.botStatusLabel.setPalette(QPalette(MyColors.lightGreen))
            self.botStatusLabel.setText("Scanning Galaxies...")
            self.startClicked() # restart the bot
        
    # bot events handler methods:
    # ------------------------------------------------------------------------

    def connectionError(self,reason):
        self.connectionStatusLabel.setText("Connection error")        
        self.connectionStatusLabel.setPalette(QPalette(MyColors.lightRed))
        self.botStatusLabel.setPalette(QPalette(MyColors.lightRed))
        self.botStatusLabel.setText("Stopped")        
        
    def loggedIn(self,username,session):
        self.scanGalaxiesButton.setEnabled(True)
        #self.startButton.setEnabled(True)
        print "Logged In"
        #self.launchBrowserButton.setEnabled(True)
        self.session = session
    def fatalException(self,exception):
        self.stopClicked()
        QMessageBox.critical(self,"Fatal error","Critical error: %s" % exception)

    def statusMsg(self,msg):
        self.setConnectionOK()        
        self.botStatusLabel.setPalette(QPalette(MyColors.lightYellow))
        self.botStatusLabel.setText(msg)       
    def connected(self):
        self.setConnectionOK()        
        self.scanGalaxiesButton.setEnabled(True)
        self.startButton.setEnabled(True)
        #self.launchBrowserButton.setEnabled(True)
        
    def myPlanetsResTableUpdate(self, myResources):
        
        #print 'in gui', myResources
        #print 'in gui', myPlanets
        totalMetal = 0
        totalCrystal  = 0
        totalDeuterium = 0
        col = 4
        inc  = 5
        row = len(myResources)/inc + 1
        
        #print 'row', row
        
        self.myPlanetResTable.setRowCount(row)
        
        for j in xrange(row-1):
            for i in xrange(col):
                newItem = QTableWidgetItem(str(myResources[i+j*inc]))
                self.myPlanetResTable.setItem(j, i, newItem)
            
            totalMetal = totalMetal  + int(myResources[1+j*inc])            
            totalCrystal  = totalCrystal + int(myResources[2+j*inc])
            totalDeuterium = totalDeuterium + int(myResources[3+j*inc])
        
        #print 'totalMetal', totalMetal
        #print 'totalCrystal', totalCrystal
        #print 'totalDeuterium', totalDeuterium
        #print 'row', row
        
        newItem = QTableWidgetItem('Total')
        self.myPlanetResTable.setItem((row-1), 0, newItem)
        newItem = QTableWidgetItem(str(totalMetal))
        self.myPlanetResTable.setItem((row-1), 1, newItem)
        newItem = QTableWidgetItem(str(totalCrystal))
        self.myPlanetResTable.setItem((row-1), 2, newItem)
        newItem = QTableWidgetItem(str(totalDeuterium))
        self.myPlanetResTable.setItem((row-1), 3, newItem)
    
    def simulationsUpdate(self,rentabilitiesTable):
        self.setConnectionOK()

        self.botActivityTree.clear() 
        maxRentability = 0
        for item in rentabilitiesTable:
            if item.rentability > maxRentability:
                maxRentability = item.rentability
                
        for item in rentabilitiesTable:

            if not item.targetPlanet.espionageHistory: 
                simulatedResources = 'Not spied'
                defendedStr = 'Not spied'
                minesStr = 'Not spied'
                lastSpiedStr = 'Not spied'
            else:
                simulatedResources = item.targetPlanet.simulation.simulatedResources

                report = item.targetPlanet.getBestEspionageReport()
                lastSpiedStr = str(report.date)                
                if  report.defense == None:
                    defendedStr = '?'
                elif not report.isDefended():
                    defendedStr = 'No'
                else:
                    defendedStr = "Yes : " + str(report.getDefensePower())
                
                if report.buildings == None:
                    minesStr = '?'
                else:
                    minesStr = "M: %s, C: %s D: %s" % (report.buildings.get('metalMine',0),report.buildings.get('crystalMine',0),report.buildings.get('deuteriumSynthesizer',0))
                     
                 
            treeItem = MyTreeWidgetItem(["%.2f" % item.rentability,str(item.targetPlanet.coords),item.targetPlanet.name,item.targetPlanet.owner,item.targetPlanet.alliance,str(simulatedResources),defendedStr,minesStr,str(item.sourcePlanet),lastSpiedStr])
            if item.targetPlanet.espionageHistory:
                treeItem.setToolTip(6,str(report.fleet) + str(report.defense))
                treeItem.setToolTip(7,str(report.buildings) + str(report.research))
                treeItem.setData(0,Qt.UserRole,QVariant(item.targetPlanet.espionageHistory[-1].toFormattedReport(self.translations)))
        
            if item.rentability > 0:
                value = int (item.rentability *  255 / maxRentability)
                backColor = QColor(255-value,255,255-value)            
                treeItem.setBackgroundColor(0,backColor)
            self.botActivityTree.addTopLevelItem(treeItem)        
            
            
    def activityMsg(self,msg):            
        self.setConnectionOK()   
        self.setBotStatusRunning()     
        item = QListWidgetItem(str(msg))
        self.botActivityList.addItem(item)
        self.botActivityList.scrollToItem(item)
                
class MyTreeWidgetItem(QTreeWidgetItem):
    def __lt__(self,other):
        sortCol = self.treeWidget().sortColumn()
        myNumber, ok1 = self.text(sortCol).toDouble()
        otherNumber, ok2 = other.text(sortCol).toDouble()
        if not ok1 or not ok2:
            return self.text(sortCol) < other.text(sortCol)
        else:
            return myNumber < otherNumber

def guiMain(options):
    app = QApplication(sys.argv)
    locale.setlocale(locale.LC_ALL,'C')
    QApplication.setStyle(QStyleFactory.create("plastique"))
    window = MainWindow()
    window.show()
    if options and options.autostart:
        window.startClicked()
    app.exec_()
    
